package cn.conac.as.gateway.base;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.netflix.hystrix.HystrixCommand;

import cn.conac.as.framework.utils.RestClientException;
import cn.conac.as.gateway.app.vo.BdtLawSrhVo;

/**
 * ClassName: BaseService
 * @author wangmeng
 * @version 1.0
 */
@SuppressWarnings("unused")
public class BaseService {

    public BaseService() {
    }

    /**
     * restTemplate
     */
    @Autowired
    protected RestTemplate restTemplate;

//    /**
//     * interceptor
//     */
//    @Autowired
//    protected LoadBalancerInterceptor interceptor;
//
//    /**
//     * setInterceptor.
//     * @param interceptor LoadBalancerInterceptor
//     */
//    @Autowired
//    public void setInterceptor(LoadBalancerInterceptor interceptor) {
//        this.interceptor = interceptor;
//        restTemplate = new RestTemplate();
//        ((SimpleClientHttpRequestFactory) restTemplate.getRequestFactory()).setReadTimeout(1000 * 50);
//        List<ClientHttpRequestInterceptor> list = new ArrayList<ClientHttpRequestInterceptor>();
//        list.add(interceptor);
//        restTemplate.setInterceptors(list);
//    }

    /**
     * GET(getForObject).
     * @param <T> 泛型对象
     * @param url String
     * @param timeOut int
     * @param responseType Class<T>
     * @param urlVariables Object
     * @return T
     * @throws RestClientException RestClient异常
     */
    public <T> T getForObject(String url, int timeOut, Class<T> responseType, Object... urlVariables)
            throws RestClientException
    {
        T obj = restTemplate.getForObject(url, responseType, urlVariables);
        int code = ((JSONObject) obj).getIntValue("code");
        String msg = ((JSONObject) obj).getString("msg");
        if (code > 1999) {
            throw new RestClientException(code, msg);
        } else {
            return obj;
        }
    }

    /**
     * GET(getForObject).
     * @param <T> 泛型对象
     * @param url String
     * @param responseType Class<T>
     * @param urlVariables Object
     * @return T
     * @throws RestClientException RestClient异常
     */
    public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws RestClientException {
        T obj = restTemplate.getForObject(url, responseType, urlVariables);
        int code = ((JSONObject) obj).getIntValue("code");
        String msg = ((JSONObject) obj).getString("msg");
        if (code > 1999) {
            throw new RestClientException(code, msg);
        } else {
            return obj;
        }
    }

    /**
     * POST(postForObject).
     * @param <T> 泛型对象
     * @param url String
     * @param timeOut int
     * @param request Object
     * @param responseType Class<T>
     * @param uriVariables Object
     * @return T
     * @throws RestClientException RestClient异常
     */
    public <T> T postForObject(String url, int timeOut, Object request, Class<T> responseType, Object... uriVariables)
            throws RestClientException {
        T obj = restTemplate.postForObject(url, request, responseType, uriVariables);
        int code = ((JSONObject) obj).getIntValue("code");
        String msg = ((JSONObject) obj).getString("msg");
        if (code > 1999) {
            throw new RestClientException(code, msg);
        } else {
            return obj;
        }
    }

    /**
     * POST(postForObject).
     * @param <T> 泛型对象
     * @param url String
     * @param request Object
     * @param responseType Class<T>
     * @param uriVariables Object
     * @return T
     * @throws RestClientException RestClient异常
     */
    public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
            throws RestClientException {
        T obj = restTemplate.postForObject(url, request, responseType, uriVariables);
        int code = ((JSONObject) obj).getIntValue("code");
        String msg = ((JSONObject) obj).getString("msg");
        if (code > 1999) {
            throw new RestClientException(code, msg);
        } else {
            return obj;
        }
    }

    // PUT
    private static final long TIMEOUT = 2 * 60 * 1000;

    private static Map<String, Map<String, Object>> doBackendAsyncServiceCall(List<Callable<AsyncResponse>> callables) {
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        try {
            List<Future<AsyncResponse>> futures = executorService.invokeAll(callables);
            executorService.shutdown();
            executorService.awaitTermination(TIMEOUT, TimeUnit.MILLISECONDS);
            Map<String, Map<String, Object>> result = new HashMap<>();
            for (Future<AsyncResponse> future : futures) {
                AsyncResponse response = future.get();
                result.put(response.serviceKey, response.response);
            }
            return result;
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    private static class AsyncResponse {
        private final String serviceKey;
        private final Map<String, Object> response;

        AsyncResponse(String serviceKey, Map<String, Object> response) {
            this.serviceKey = serviceKey;
            this.response = response;
        }
    }

    private static class BackendServiceCallable implements Callable<AsyncResponse> {
        private final String serviceKey;
        private final HystrixCommand<Map<String, Object>> hystrixCommand;

        public BackendServiceCallable(String serviceKey, HystrixCommand<Map<String, Object>> hystrixCommand) {
            this.serviceKey = serviceKey;
            this.hystrixCommand = hystrixCommand;
        }

        @Override
        public AsyncResponse call() throws Exception {
            return new AsyncResponse(serviceKey, hystrixCommand.execute());
        }
    }
    
//    //例子
//    @Cacheable
//    private HystrixCommand<Map<String, Object>> getProductDetails(String productId) {
//        return new HystrixCommand<Map<String, Object>>(
//                HystrixCommand.Setter
//                        .withGroupKey(HystrixCommandGroupKey.Factory.asKey(GROUP))
//                        .andCommandKey(HystrixCommandKey.Factory.asKey("getProductDetails"))
//                        .andCommandPropertiesDefaults(
//                                HystrixCommandProperties.Setter()
//.withExecutionIsolationThreadTimeoutInMilliseconds(TIMEOUT)
//                        )
//        ) {
//            @Override
//            protected Map<String, Object> run() throws Exception {
//                return productDetailService.getDetails(productId);
//            }
//            @Override
//            protected Map getFallback() {
//                return new HashMap<>();
//            }
//        };
//    }

	public String getHttp(String url) {
		String responseMsg = "";
		HttpClient httpClient = new HttpClient();
		GetMethod getMethod = new GetMethod(url);
		getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler());
		try {
			httpClient.executeMethod(getMethod);
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			InputStream in = getMethod.getResponseBodyAsStream();
			int len = 0;
			byte[] buf = new byte[1024];
			while((len=in.read(buf))!=-1){
				out.write(buf, 0, len);
			}
			responseMsg = out.toString("UTF-8");
		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//释放连接
			getMethod.releaseConnection();
		}
		return responseMsg;
	}

	public String postHttp(String url,String searchType, BdtLawSrhVo searchCondition) {
		String responseMsg = "";
		HttpClient httpClient = new HttpClient();
		httpClient.getParams().setContentCharset("UTF-8");
		PostMethod postMethod = new PostMethod(url + searchType);
		
		// 法律法规标题
		if(StringUtils.isNotBlank(searchCondition.getTitle())){
			postMethod.addParameter("title", searchCondition.getTitle());
		}
		// 发文字号
		if(StringUtils.isNotBlank(searchCondition.getDocumentNo()) && !"none".equals(searchCondition.getDocumentNo())){
			postMethod.addParameter("DocumentNO", searchCondition.getDocumentNo());
		}
		// 每页数量(筛选结果每页数量默认20)
		if(StringUtils.isNotBlank(searchCondition.getPageSize())){
			postMethod.addParameter("PageSize", searchCondition.getPageSize());
		}
		// 当前页索引(当前页索引默认0)
		if(StringUtils.isNotBlank(searchCondition.getPageIndex())){
			postMethod.addParameter("PageIndex", searchCondition.getPageIndex());
		}
		// 条
		if(StringUtils.isNotBlank(searchCondition.getTiao())){
			postMethod.addParameter("tiao", searchCondition.getTiao());
		}
		// 款
		if(StringUtils.isNotBlank(searchCondition.getKuan())){
			postMethod.addParameter("kuan", searchCondition.getKuan());
		}
		// 项
		if(StringUtils.isNotBlank(searchCondition.getXiang())){
			postMethod.addParameter("xiang", searchCondition.getXiang());
		}
        //
        if(StringUtils.isNotBlank(searchCondition.getModelGid())){
            postMethod.addParameter("Model.Gid", searchCondition.getModelGid());
        }
        //
        if(StringUtils.isNotBlank(searchCondition.getUpdateTime())){
            postMethod.addParameter("Model.updatetime", searchCondition.getUpdateTime());
        }
        //
        if(StringUtils.isNotBlank(searchCondition.getModelTitle())){
            postMethod.addParameter("Model.Title", searchCondition.getModelTitle());
        }
        // 数据库标识
        if(StringUtils.isNotBlank(searchCondition.getLibrary())){
            postMethod.addParameter("Library", searchCondition.getLibrary());
        }
		
		try {
			httpClient.executeMethod(postMethod);
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			InputStream in = postMethod.getResponseBodyAsStream();
			int len = 0;
			byte[] buf = new byte[1024];
			while((len=in.read(buf))!=-1){
				out.write(buf, 0, len);
			}
			responseMsg = out.toString("UTF-8");
		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			postMethod.releaseConnection();
		}
		return responseMsg;
	}
}
